home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v10n15.arc / STRINGS.ASM < prev    next >
Assembly Source File  |  1991-08-09  |  82KB  |  2,202 lines

  1.             page    66,132
  2. ;============================================================================
  3. ; STRINGS.COM - a set of string handling functions for batch files.
  4. ;
  5. ; Syntax:
  6. ;       STRINGS [/H][/M][/Pc ][var = ] function arg1 [, arg2] [, arg3]
  7. ;
  8. ;       /?  - Print help message
  9. ;       /M  - Use master environment block
  10. ;       /Pc - Use c as parse character instead of ','
  11. ;
  12. ; Revision History:
  13. ;
  14. ;       Version 1.0     Initial Release
  15. ;
  16. ;============================================================================
  17.  
  18.             code    segment
  19.             assume  cs:code
  20.  
  21.             org     2ch
  22. local_environment       dw      ?               ;Word containing the segment
  23.                                             ;  of the program's env. block.
  24.             org     80h
  25. command_tail    db      ?                       ;Offset of the command tail.
  26.  
  27.             org     100h
  28.  
  29. main:           jmp     initialize
  30. program         db      13,10,"STRINGS 1.0 "
  31. copyright       db      "(c) 1991 Douglas Boling",10,13
  32.                 db      "First published in PC Magazine, September 10, 1991"
  33.             db      10,13,10,"$",1Ah
  34.  
  35. VAR_SIZE        equ     128                     ;Max size of variables
  36. DATABUFF_SIZE   equ     16384                   ;Size of file data buffer
  37.  
  38. command_table   db      "LEFT",0                ;String functions
  39.             db      "RIGHT",0
  40.             db      "MID",0
  41.             db      "LENGTH",0
  42.             db      "FIND",0
  43.             db      "FINDC",0
  44.             db      "LOWER",0
  45.             db      "UPPER",0
  46.             db      "CHAR",0
  47.             db      "VAL",0
  48.             db      "FILENAME",0
  49.             db      "FILEEXT",0
  50.  
  51.             db      "READ",0                ;File functions
  52.             db      "WRITE",0
  53.             db      "FILESIZE",0
  54.             db      "LINESIZE",0
  55.             db      "TRUENAME",0
  56.  
  57.             db      "VER",0                 ;System functions
  58.             db      "ASK",0
  59.             db      "ENVFREE",0
  60.             db      "ENVSIZE",0
  61.             db      "MASTERVAR",0
  62.  
  63.             db      "ADD",0                 ;Math functions
  64.             db      "SUB",0
  65.             db      "MUL",0
  66.             db      "DIV",0
  67.             db      0                       ;End of list flag
  68.  
  69. jump_table      dw      offset left_str
  70.             dw      offset right_str
  71.             dw      offset mid_str
  72.             dw      offset length_str
  73.             dw      offset find_str
  74.             dw      offset findc_str
  75.             dw      offset lower_str
  76.             dw      offset upper_str
  77.             dw      offset char_str
  78.             dw      offset val_str
  79.             dw      offset filename_str
  80.             dw      offset fileext_str
  81.  
  82.             dw      offset readrec_file
  83.             dw      offset writerec_file
  84.             dw      offset filesize_file
  85.             dw      offset numrec_file
  86.             dw      offset truename_file
  87.     
  88.             dw      offset ver_sys
  89.             dw      offset ask_sys
  90.             dw      offset envfree_sys
  91.             dw      offset envsize_sys
  92.             dw      offset mastervar_sys
  93.  
  94.             dw      offset add_num
  95.             dw      offset sub_num
  96.             dw      offset mul_num
  97.             dw      offset div_num
  98. jump_table_end  =       $
  99.  
  100. parse_char      db      ","                     ;Char used to parse command
  101. fill_char       db      " "                     ;Char used to fill zeros
  102. equalsub_char   db      0cdh
  103.  
  104. databuff_ptr    dw      0                       ;Ptr to file data buffer
  105.  
  106. environment_seg dw      0                       ;Segment of master env
  107. dos_version     dw      0
  108. shell_name      db      "COMMAND"
  109. console_out     db      1                       ;Flag for con out.
  110. use_mastenv     db      0                       ;Flag to use master env
  111. parse_literal    db    0            ;Flag to respect lead spaces
  112.  
  113. dest_var_val    dw      0
  114. dest_var_name   dw      0                       ;Buffer pointers to parsed
  115. cmd_value       dw      0                       ;  command line variables.
  116. var1_value      dw      0                       ;  These pointers must be
  117. var2_value      dw      0                       ;  kept in this order for the
  118. var3_value      dw      0                       ;  cmdline parse routine.
  119.  
  120. hlpmsg          db      13,10,"Usage: STRINGS [/H][/M][/Pc][environment var =]"
  121.             db      " FUNCTION [str1][, str2][, str3]",13,10,13,10
  122.             db      " /?  - Print this help message",13,10
  123.             db      " /M  - Use master environment as destination",13,10
  124.             db      " /Pc - Use char c instead of ',' as the parse "
  125.             db      "character",13,10,10
  126.     db      " LEFT      Returns left n chars                    "
  127.     db      "String,  Num of chars",13,10
  128.     db      " RIGHT     Returns right n chars                   "
  129.     db      "String,  Num of chars",13,10
  130.     db      " MID       Returns middle n chars                  "
  131.     db      "String,  Start char,  Length",13,10
  132.     db      " LENGTH    Returns string length                   "
  133.     db      "String",13,10
  134.     db      " FIND      Finds position of findstring            "
  135.     db      "String, findstring",13,10
  136.     db      " FINDC     Finds position of findstring. Case sen  "
  137.     db      "String, findstring",13,10,0
  138. hlpmsga db      " LOWER     Returns string all lowercase            "
  139.     db      "String",13,10
  140.         db      " UPPER     Returns string all uppercase            "
  141.     db      "String",13,10
  142.     db      " CHAR      Returns ASCII number of character       "
  143.     db      "Character",13,10
  144.     db      " VAL       Returns ASCII char for a number         "
  145.     db      "Number",13,10,10
  146.  
  147.     db      " READ      Returns a line from a file              "
  148.     db      "Filename, line number",13,10
  149.     db      " WRITE     Writes a string to the end of a file    "
  150.     db      "Filename, String",13,10
  151.     db      " FILESIZE  Returns the size of a file              "
  152.     db      "Filename",13,10
  153.     db      " LINESIZE  Returns the number of lines             "
  154.     db      "Filename",13,10,0
  155. hlpmsgb db      " FILENAME  Returns the file name                   "
  156.     db      "Filename",13,10
  157.     db      " FILEEXT   Returns the file extension              "
  158.     db      "Filename",13,10
  159.     db      " TRUENAME  Returns the complete filename           "
  160.     db      "Filename",13,10,10
  161.  
  162.     db      " ASK       Returns a response from a user          "
  163.     db      "[Prompt string]",13,10
  164.     db      " VER       Returns the DOS version number",13,10
  165.     db      " ENVFREE   Returns the bytes free in the environment",13,10
  166.     db      " ENVSIZE   Returns the size of the environment",13,10
  167.     db      " MASTERVAR Returns a variable from the Master env  ",13,10,10
  168.  
  169.     db      " ADD       Returns the sum of two numbers          "
  170.     db      "Number, Number",13,10
  171.     db      " SUB       Returns the difference of two numbers   "
  172.     db      "Number, Number",13,10
  173.     db      " MUL       Returns the product of two numbers      "
  174.     db      "Number, Number",13,10
  175.     db      " DIV       Returns the quotient of two numbers     "
  176.     db      "Number, Number",13,10
  177.     db      0
  178.  
  179. errmsg0         db      "Need DOS 2.0 or greater",0
  180. errmsg1         db      "For help type STRINGS /?",0
  181. errmsg2         db      "Not enought memory",0
  182. errmsg3         db      "Unknown command line switch",0
  183. errmsg6         db      "Illegal filename",0
  184. errmsg7         db      "Line numbers must be greater than 0",0
  185. errmsg8         db      "Line not found",0
  186. errmsg9         db      "DOS error",0
  187.  
  188. errmsg10        db      "Multiply overflow error",0
  189. errmsg11        db      "Divide by zero error",0
  190. errmsg12        db      "Addition overflow",0
  191. errmsg13        db      "Subtraction underflow",0
  192. errmsg14        db      "Number too large",0
  193. errmsg15        db      "Out of environment space",0
  194. errmsg16        db      "Can't find environment",0
  195. errmsg17        db      "Variable not found",0
  196.  
  197. pausemsg    db    "Press any key to continue",13,10,0
  198. endmsg          db      13,10,0
  199.  
  200. ;----------------------------------------------------------------------------
  201. ; Start of code.
  202. ;----------------------------------------------------------------------------
  203. initialize      proc    near
  204.             assume  cs:code,ds:code,es:code
  205.             cld                             ;Set string operations 'up.'
  206.  
  207.             mov     ah,30h                  ;Get DOS version, run only
  208.             int     21h                     ;  if 2.0 or greater.
  209.             xchg    al,ah                   ;Swap major, minor numbers
  210.             mov     dos_version,ax
  211.             mov     si,offset errmsg0       ;Bad DOS version
  212.             cmp     ah,2
  213.             jae     main_1
  214.             jmp     disp_error
  215. main_1:
  216.             mov     di,offset end_of_code + 512     ;Set up data buffers
  217.             mov     sp,di                   ;Set stack
  218.             mov     si,offset dest_var_val
  219.             mov     cx,6                    ;Set buffer pointers
  220.             xor     ax,ax
  221. main_2:
  222.             mov     [si],di                 ;Save ptr to buffer
  223.             push    cx
  224.             mov     cx,VAR_SIZE             ;Initialize buffer to zero
  225.             rep     stosb
  226.             pop     cx
  227.             inc     si
  228.             inc     si
  229.             loop    main_2
  230.             mov     databuff_ptr,di         ;Save data buffer ptr
  231.  
  232.             mov     bx,DATABUFF_SIZE
  233.             add     bx,di
  234.             mov     cl,4
  235.             shr     bx,cl
  236.             inc     bx
  237.             mov     ah,4ah                  ;Reduce memory allocation
  238.             int     21h
  239.  
  240.             call    parse_cmdline           ;Parse command line
  241.             jc      disp_error
  242.  
  243.             mov     si,dest_var_name        ;Point to dest env var name
  244.             call    caps_string
  245.  
  246.             mov     si,cmd_value            ;Point to command buffer
  247.             call    caps_string
  248.  
  249.             mov     di,offset command_table
  250.             call    findstr
  251.             mov     si,offset errmsg1
  252.             jc      disp_error
  253.             shl     bx,1                    ;Compute offset of routine to
  254.             add     bx,offset jump_table    ;  call.
  255.             call    [bx]                    ;Call routine to compile line.
  256.             jc      disp_error
  257.  
  258.             mov     si,dest_var_val
  259.             cmp     console_out,0           ;See how to return result
  260.             je      main_3
  261.             call    print_strcr             ;Print result string to screen
  262.             jmp     short main_6
  263. main_3:
  264.             mov     di,dest_var_name
  265.             xchg    di,si
  266.  
  267.             cmp     use_mastenv,0        ;Find environment block
  268.             jne     main_4
  269.             call    findenv                 ;Use parent's env by default.
  270.             jnc     main_5
  271. main_4:
  272.             call    findmaster              ;Find master env
  273.             jc      disp_error
  274. main_5:
  275.             mov     environment_seg,ax
  276.  
  277.             call    setenv                  ;Set environemnt variable.
  278.             jc      main_7
  279. main_6:
  280.             xor     al,al                   ;Return code = 0
  281. exit:
  282.             mov     ah,4Ch                  ;Terminate
  283.             int     21h
  284. ;
  285. ;Display error message.
  286. ;
  287. main_7:
  288.             mov     si,offset errmsg15      ;Out of environment space
  289. disp_error:
  290.             push    cs
  291.             pop     ds
  292.             assume  ds:code
  293.  
  294.             mov     ah,9                    ;Print copyright message
  295.             mov     dx,offset program
  296.             int     21h
  297.  
  298.         push    si
  299.             call    print_strcr             ;print string
  300.         pop    si
  301.         cmp    si,offset hlpmsg
  302.         jne    main_9
  303.         mov    ax,40h
  304.         mov    es,ax
  305.         mov    al,es:[84h]
  306.         cmp    al,42
  307.         ja    main_8
  308.  
  309.         call    pause_scr            
  310.         mov    si,offset hlpmsga
  311.         call    print_strcr
  312.  
  313.         call    pause_scr            
  314.         mov    si,offset hlpmsgb
  315.         call    print_strcr
  316.         jmp    short main_9
  317. main_8:
  318.         mov    si,offset hlpmsga
  319.         call    print_strcr
  320.         mov    si,offset hlpmsgb
  321.         call    print_strcr
  322. main_9:    
  323.             mov     al,01                   ;Terminate with RC = 1
  324.             jmp     short exit
  325.  
  326. ;=============================================================================
  327. ; String Functions
  328. ;=============================================================================
  329. ;-----------------------------------------------------------------------------
  330. ; RIGHT STR  returns the right n characters of the source string
  331. ;-----------------------------------------------------------------------------
  332. right_str       proc    near
  333.             assume  cs:code,ds:code,es:code
  334.             mov     si,var2_value           ;Convert 2nd parameter to hex
  335.             call    asc2hex
  336.             call    truncnum                ;Truncate number to string len
  337.  
  338.             push    ax
  339.             mov     di,var1_value           ;Scan to end of string
  340.             call    find_end
  341.             pop     ax
  342. right_str_2:
  343.             sub     di,ax
  344.             dec     di
  345.             cmp     di,var1_value
  346.             ja      right_str_3
  347.             mov     di,var1_value
  348. right_str_3:
  349.             mov     si,dest_var_val
  350.             xchg    di,si
  351.             call    copy_string             ;Copy string to dest buffer
  352.             clc
  353.             ret
  354. right_str       endp
  355.  
  356. ;-----------------------------------------------------------------------------
  357. ; LEFT STR Returns the left n characters of the source string
  358. ;-----------------------------------------------------------------------------
  359. left_str        proc    near
  360.             assume  cs:code,ds:code,es:code
  361.             mov     si,var2_value           ;Convert 2nd parameter to hex
  362.             call    asc2hex
  363.             call    truncnum                ;Truncate number to string len
  364.  
  365.             mov     si,var1_value
  366.             mov     bx,ax
  367.             mov     byte ptr [si+bx],0
  368.  
  369.             mov     di,dest_var_val
  370.             call    copy_string             ;Copy string to dest buffer
  371.             clc
  372.             ret
  373. left_str        endp
  374.  
  375. ;-----------------------------------------------------------------------------
  376. ; MID STR Returns a string of n characters starting m characters from the
  377. ;         left of the source string
  378. ;-----------------------------------------------------------------------------
  379. mid_str         proc    near
  380.             assume  cs:code,ds:code,es:code
  381.             mov     si,var2_value           ;Convert 2nd parameter to hex
  382.             call    asc2hex
  383.             dec     ax
  384.             call    truncnum                ;Truncate number to string len
  385.             mov     cx,ax                   ;Copy second parameter
  386.  
  387.             mov     si,var3_value           ;Convert 3rd parameter to hex
  388.             cmp     byte ptr [si],0         ;See if no parameter
  389.             je      mid_str_0
  390.             call    asc2hex                 ;If no number, return max
  391.             jnc     mid_str_1               ;  value to insure remainder
  392. mid_str_0:
  393.             mov     ax,VAR_SIZE             ;  of string returned.
  394. mid_str_1:
  395.             call    truncnum                ;Truncate number to string len
  396.  
  397.             push    ax                      ;Save length of substring
  398.             xor     ax,ax
  399.             cmp     al,1                    ;Clear zero flag
  400.             mov     di,var1_value           ;Scan to new start of string
  401.             jcxz    mid_str_11
  402.             repne   scasb
  403. mid_str_11:
  404.             pop     cx                      ;Pop length of substring
  405.             mov     si,di                   ;Copy ptr to start of substr
  406.             je      mid_str_2               ;If end of str found, end
  407.  
  408.             repne   scasb                   ;Scan until end of substring
  409.             mov     byte ptr [di],0
  410. mid_str_2:
  411.             mov     di,dest_var_val
  412.             call    copy_string             ;Copy string to dest buffer
  413.             clc
  414.             ret
  415. mid_str         endp
  416.  
  417. ;-----------------------------------------------------------------------------
  418. ; LENGTH STR Computes the length of the source string
  419. ;-----------------------------------------------------------------------------
  420. length_str      proc    near
  421.             assume  cs:code,ds:code,es:code
  422.             mov     di,var1_value           ;Find_end also returns the
  423.             call    find_end                ;  length of the string in
  424.             mov     ax,cx                   ;  CX.
  425.             xor     dx,dx
  426.             mov     di,dest_var_val         ;Convert value to ASCII
  427.             call    hex2asc
  428.             clc
  429.             ret
  430. length_str      endp
  431.  
  432. ;-----------------------------------------------------------------------------
  433. ; UPPER STR Convert the source string to upper case
  434. ;-----------------------------------------------------------------------------
  435. upper_str       proc    near
  436.             assume  cs:code,ds:code,es:code
  437.             mov     di,dest_var_val
  438.             mov     si,var1_value
  439.             push    di
  440.             call    copy_string             ;Copy string to dest buffer
  441.             pop     si
  442.             call    caps_string             ;Convert to upper case.
  443.             clc
  444.             ret
  445. upper_str       endp
  446.  
  447. ;-----------------------------------------------------------------------------
  448. ; LOWER STR Convert the source string to lower case
  449. ;-----------------------------------------------------------------------------
  450. lower_str       proc    near
  451.             assume  cs:code,ds:code,es:code
  452.             mov     di,dest_var_val
  453.             mov     si,var1_value
  454.             push    di
  455.             call    copy_string             ;Copy string to dest buffer
  456.             pop     si
  457.             call    lc_string               ;Convert to lower case.
  458.             clc
  459.             ret
  460. lower_str       endp
  461.  
  462. ;-----------------------------------------------------------------------------
  463. ; CHAR STR Convert the source number to a ASCII character
  464. ;-----------------------------------------------------------------------------
  465. char_str        proc    near
  466.             assume  cs:code,ds:code,es:code
  467.             mov     si,var1_value           ;Convert ASCII number to hex
  468.             call    asc2hex
  469.             mov     di,dest_var_val
  470.             xor     ah,ah                   ;Write number directly to
  471.             stosw                           ;  dest string.  Include
  472.             clc                             ;  zero for termination.
  473.             ret
  474. char_str        endp
  475.  
  476. ;-----------------------------------------------------------------------------
  477. ; VAL STR Convert the source character to its HEX equivalent
  478. ;-----------------------------------------------------------------------------
  479. val_str         proc    near
  480.             assume  cs:code,ds:code,es:code
  481.             mov     si,var1_value           ;Get ASCII character, then
  482.             lodsb                           ;  write its hex equivalent
  483.             xor     ah,ah                   ;  to the output var.
  484.             xor     dx,dx
  485.             mov     di,dest_var_val
  486.             call    hex2asc
  487.             clc
  488.             ret
  489. val_str         endp
  490.  
  491. ;-----------------------------------------------------------------------------
  492. ; FILENAME STR Return only the filename from a filename string
  493. ;-----------------------------------------------------------------------------
  494. filename_str    proc    near
  495.             assume  cs:code,ds:code,es:code
  496.             mov     si,var1_value           ;Fully qualify filename
  497.             mov     di,var2_value           ;Use 2nd buff as temp buff
  498.             call    parse_filename
  499.             mov     si,di
  500.             mov     bx,di
  501. filename_1:
  502.             lodsb
  503.             cmp     al,'\'                  ;Mark start of filename or
  504.             jne     filename_2              ;  directory.
  505.             mov     bx,si
  506. filename_2:
  507.             or      al,al
  508.             je      filename_3
  509.             cmp     al,'.'
  510.             jne     filename_1
  511.             dec     si
  512. filename_3:
  513.             mov     cx,si
  514.             sub     cx,bx                   ;Compute length
  515.             mov     di,dest_var_val
  516.             mov     si,bx
  517.             rep     movsb
  518.             clc
  519.             ret
  520. filename_str    endp
  521.  
  522. ;-----------------------------------------------------------------------------
  523. ; FILEEXT STR Return only the filename extension from a filename string
  524. ;-----------------------------------------------------------------------------
  525. fileext_str     proc    near
  526.             assume  cs:code,ds:code,es:code
  527.             mov     si,var1_value           ;Fully qualify filename
  528.             mov     di,var2_value           ;Use 2nd buff as temp buff
  529.             call    parse_filename
  530.             mov     si,di
  531.             xor     bx,bx
  532. fileext_1:
  533.             lodsb
  534.             cmp     al,'.'                  ;Mark start of filename or
  535.             jne     fileext_2               ;  directory.
  536.             mov     bx,si
  537. fileext_2:
  538.             or      al,al
  539.             jne     fileext_1
  540.  
  541.             or      bx,bx
  542.             je      fileext_3
  543.             mov     cx,si
  544.             sub     cx,bx                   ;Compute length
  545.             mov     di,dest_var_val
  546.             mov     si,bx
  547.             rep     movsb
  548. fileext_3:
  549.             clc
  550.             ret
  551. fileext_str     endp
  552.  
  553. ;-----------------------------------------------------------------------------
  554. ; FIND STR  finds a string within another string.
  555. ; Exit:      AL - Return code if string not found
  556. ;            CF - Set if string not found
  557. ;-----------------------------------------------------------------------------
  558. find_str        proc    near
  559.             mov     si,var1_value           ;To ignore case, capitalize
  560.             call    caps_string             ;  both strings, then call
  561.             mov     si,var2_value           ;  the findc function.
  562.             call    caps_string
  563.             call    findc_str
  564.             ret
  565. find_str        endp
  566.  
  567. ;-----------------------------------------------------------------------------
  568. ; FINDC STR  finds a string within another string, respects case.
  569. ; Exit:      AL - Return code if string not found
  570. ;            CF - Set if string not found
  571. ;-----------------------------------------------------------------------------
  572. findc_str       proc    near
  573.             mov     di,var1_value           ;Get ptr to 1st string
  574.             push    di
  575.             call    find_end                ;Compute length
  576.             pop     si
  577.             push    cx                      ;Save length
  578.             mov     di,var2_value
  579.             mov     dx,di
  580.             call    find_end
  581.             mov     bx,cx                   ;Save length of search string
  582.             pop     cx                      ;Restore length of trg string
  583.             sub     cx,bx                   ;Sub length of search string.
  584.             jb      find_str_not_found
  585.         inc    cx
  586. find_str_1:
  587.             push    cx
  588.             mov     cx,bx                   ;Restore search str length
  589.             mov     di,dx                   ;Restore ptr to search str
  590.             push    si
  591.             repe    cmpsb                   ;Compare command
  592.             pop     si
  593.             pop     cx
  594.             je      find_str_found
  595.             inc     si                      ;Inc target string ptr
  596.             loop    find_str_1
  597. find_str_not_found:
  598.             xor     ax,ax                   ;Set bad return code
  599.             jmp     short find_str_2
  600. find_str_found:
  601.             mov     ax,si                   ;Copy offset
  602.             sub     ax,var1_value           ;Sub starting offset
  603.             inc     ax
  604. find_str_2:
  605.             xor     dx,dx
  606.             mov     di,dest_var_val         ;Convert value to ASCII
  607.             call    hex2asc
  608.             clc
  609. find_str_exit:
  610.             ret
  611. findc_str       endp
  612. ;=============================================================================
  613. ; File Functions
  614. ;=============================================================================
  615. ;-----------------------------------------------------------------------------
  616. ; READ REC returns record n from a file.
  617. ;-----------------------------------------------------------------------------
  618. readrec_file    proc    near
  619.             assume  cs:code,ds:code,es:code
  620.  
  621.             mov     si,var1_value           ;Fully qualify filename
  622.             mov     di,dest_var_val         ;Use dest buff as temp buff
  623.             call    parse_filename
  624.             mov     dx,di                   ;Copy filename pointer
  625.             call    open_file
  626.             jc      readrec_error
  627.  
  628.             mov     si,var2_value           ;Convert 2nd param to record
  629.             call    asc2hex                 ;  number.
  630.  
  631.             call    findrec_file            ;Find record.
  632.             mov     ax,si                   ;Copy end of file flag.
  633.             mov     si,offset errmsg8       ;Record not found.
  634.             jc      readrec_error1          ;Error if record not found.
  635.  
  636.             mov     si,dest_var_val
  637.             xchg    di,si
  638.             jcxz    readrec_2
  639. readrec_1:
  640.             lodsb                           ;Copy record to destination
  641.             cmp     al,13                   ;  buffer.
  642.             je      readrec_3
  643.             stosb
  644.             loop    readrec_1
  645. readrec_2:
  646.             or      ah,ah                   ;Check end of file flag
  647.             jne     readrec_3
  648.             mov     dx,databuff_ptr         ;If at end of data buffer.
  649.             mov     cx,VAR_SIZE             ;  read enough to complete
  650.             call    read_file               ;  record.
  651.             jc      readrec_error
  652.             mov     cx,ax                   ;Copy number of bytes read.
  653.             mov     di,dx
  654.             jmp     short readrec_1
  655. readrec_3:
  656.             xor     al,al                   ;Append terminating zero
  657.             stosb
  658.             call    close_file              ;Close file
  659.             jc      readrec_error
  660. readrec_exit:
  661.             ret
  662. readrec_error:
  663.             mov     si,offset errmsg9       ;Generic DOS error msg
  664.             stc
  665.             jmp     short readrec_exit
  666. readrec_error1:
  667.             call    close_file
  668.             stc
  669.             jmp     short readrec_exit
  670. readrec_file    endp
  671.  
  672. ;-----------------------------------------------------------------------------
  673. ; WRITE REC appends a string to the end of a file.
  674. ;-----------------------------------------------------------------------------
  675. writerec_file   proc    near
  676.             assume  cs:code,ds:code,es:code
  677.  
  678.             mov     si,var1_value           ;Fully qualify filename
  679.             mov     di,dest_var_val         ;Use dest buff as temp buff
  680.             call    parse_filename
  681.             mov     dx,di                   ;Copy filename pointer
  682.             call    open_file               ;Open file.  If file does not
  683.             jnc     writerec_0              ;  exist, create the file.
  684.             call    create_file
  685.             jc      writerec_error
  686.             mov     si,1
  687.             jmp     short writerec_1
  688. writerec_0:
  689.             xor     ax,ax                   ;Move file ptr to end of file
  690.             cwd
  691.             mov     cx,2                    ;Move pointer from end.
  692.             call    move_fileptr            ;Move file pointer
  693.             jc      writerec_error
  694.             mov     si,1
  695.             or      dx,dx
  696.             jne     writerec_01
  697.             or      ax,ax
  698.             je      writerec_1
  699. writerec_01:
  700.             mov     ax,-1                   ;Move file ptr to last byte
  701.             cwd
  702.             mov     cx,2                    ;Move pointer from end.
  703.             call    move_fileptr            ;Move file pointer
  704.             jc      writerec_error
  705.             dec     si                      ;Clear EOF marker flag
  706.     
  707.             mov     dx,dest_var_val         ;Read last char to check for
  708.             mov     cx,1                    ;  EOF marker
  709.             call    read_file
  710.             jc      writerec_error
  711.  
  712.             mov     di,dx
  713.             cmp     byte ptr [di],1Ah
  714.             jne     writerec_1
  715.  
  716.             mov     ax,-1                   ;See if last byte 1A EOF mark
  717.             cwd
  718.             mov     cx,2                    ;Move pointer from end.
  719.             call    move_fileptr            ;Move file pointer
  720.             jc      writerec_error
  721.             inc     si                      ;Set EOF marker flag
  722. writerec_1:
  723.             mov     di,var2_value           ;Get length of string
  724.             mov     dx,di
  725.             call    find_end
  726.             dec     di                      ;Backup before zero
  727.             mov     ax,0a0dh
  728.             stosw
  729.             inc     cx
  730.             inc     cx
  731.             or      si,si
  732.             je      writerec_2
  733.             mov     al,1ah                  ;Append EOF marker
  734.             stosb
  735.             inc     cx
  736. writerec_2:
  737.             call    write_file
  738.             jc      writerec_error
  739.  
  740.             call    close_file              ;Close file
  741.             jc      writerec_error
  742. writerec_exit:
  743.             mov     di,dest_var_val         ;Clear dest value.
  744.             mov     byte ptr [di],0
  745.             ret
  746. writerec_error:
  747.             mov     si,offset errmsg9       ;Generic DOS error msg
  748.             stc
  749.             jmp     short writerec_exit
  750. writerec_error1:
  751.             call    close_file
  752.             stc
  753.             jmp     short writerec_exit
  754. writerec_file   endp
  755.  
  756. ;-----------------------------------------------------------------------------
  757. ; NUMREC FILE returns the number of records in a file.
  758. ;-----------------------------------------------------------------------------
  759. numrec_file     proc    near
  760.             assume  cs:code,ds:code,es:code
  761.  
  762.             mov     si,var1_value           ;Fully qualify filename
  763.             mov     di,dest_var_val         ;Use dest buff as temp buff
  764.             call    parse_filename
  765.             mov     dx,di                   ;Copy filename pointer
  766.             call    open_file
  767.             jc      numrec_error
  768.  
  769.             xor     ax,ax                   ;Attempt to find large rec num
  770.             mov     dx,ax
  771.  
  772.             call    findrec_file            ;Find record.
  773.             jnc     numrec_error1           ;Error if record found.
  774.  
  775.             not     ax                      ;Compliment line count.  No
  776.             not     dx                      ;  need to add 1 since count
  777.                                             ;  already 1 too many.
  778.             mov     di,dest_var_val         ;Convert rec number to ASCII
  779.             call    hex2asc
  780.  
  781.             call    close_file              ;Close file
  782.             jc      numrec_error
  783. numrec_exit:
  784.             ret
  785. numrec_error:
  786.             mov     si,offset errmsg9       ;Generic DOS error msg
  787.             stc
  788.             jmp     short numrec_exit
  789. numrec_error1:
  790.             call    close_file
  791.             jc      numrec_error
  792.             stc
  793.             jmp     short numrec_exit
  794. numrec_file     endp
  795.  
  796. ;-----------------------------------------------------------------------------
  797. ; FIND REC returns an offset to the Nth record of a file.
  798. ; Entry: DX,AX - Record to find
  799. ;        BX - Source File handle
  800. ; Exit:  DX,AX - Records remaing if end of file
  801. ;        CF - Set if record not found.
  802. ;        DI - Points to record.
  803. ;        CX - Number of bytes to end of data buffer
  804. ;        SI - Points to error message if CF set.
  805. ;-----------------------------------------------------------------------------
  806. findrec_numl    equ     word ptr [bp-2]
  807. findrec_numh    equ     word ptr [bp-4]
  808. findrec_eof     equ     byte ptr [bp-5]
  809. findrec_file    proc    near
  810.             assume  cs:code,ds:code,es:code
  811.             push    bp
  812.             mov     bp,sp
  813.             sub     sp,6
  814.  
  815.             mov     si,offset errmsg8       ;Record not found
  816.             mov     findrec_eof,0           ;Clear end of file flag.
  817.             mov     findrec_numl,ax         ;Save record number.
  818.             mov     findrec_numh,dx
  819. findrec_1:
  820.             mov     cx,databuff_ptr
  821.             xchg    cx,dx
  822.  
  823.             mov     cx,DATABUFF_SIZE        ;Get size of data buffer
  824.             call    read_file               ;Read data from file.
  825.             jc      findrec_error
  826.  
  827.             cmp     ax,cx                   ;See if buffer filled.  If
  828.             je      findrec_2               ;  not, end of file.
  829.             mov     findrec_eof,1           ;Set end of file flag.
  830. findrec_2:
  831.             mov     cx,ax                   ;Copy num bytes read.
  832.             mov     di,dx                   ;Copy buffer ptr
  833.             mov     dx,ax                   ;Save size of buffer
  834.  
  835.             mov     al,13                   ;Scan for CR
  836. findrec_3:
  837.             sub     findrec_numl,1          ;Decriment record count
  838.             sbb     findrec_numh,0
  839.  
  840.             jne     findrec_4               ;See if record count = 0
  841.             cmp     findrec_numl,0
  842.             je      findrec_5
  843. findrec_4:
  844.             repne   scasb
  845.             je      findrec_3
  846.             cmp     findrec_eof,1           ;If end of buffer, see if
  847.             jne     findrec_1               ;  end of file. Yes = exit
  848.             stc
  849.             jmp     short findrec_exit
  850. findrec_5:
  851.             cmp     byte ptr [di],0ah       ;discard Line feed
  852.             jne     findrec_6
  853.             inc     di
  854.             dec     cx
  855. findrec_6:
  856.             clc
  857. findrec_exit:
  858.             mov     ah,findrec_eof
  859.             mov     al,0
  860.             mov     si,ax                   ;Save end of file flag
  861.  
  862.             mov     ax,findrec_numl         ;Get record number.
  863.             mov     dx,findrec_numh
  864.  
  865.             mov     sp,bp
  866.             pop     bp
  867.             ret
  868. findrec_error:
  869.             mov     si,offset errmsg9       ;Generic DOS error msg
  870. findrec_error1:
  871.             stc
  872.             jmp     short findrec_exit
  873. findrec_file    endp
  874.  
  875. ;-----------------------------------------------------------------------------
  876. ; FILE SIZE  returns the size of a file
  877. ;-----------------------------------------------------------------------------
  878. filesize_file   proc    near
  879.             assume  cs:code,ds:code,es:code
  880.             mov     si,var1_value           ;Fully qualify filename
  881.             mov     di,dest_var_val         ;Use dest buff as temp buff
  882.             call    parse_filename
  883.             mov     dx,di                   ;Copy filename pointer
  884.             call    open_file
  885.             mov     di,dest_var_val         ;Point DI to result buffer.
  886.             jc      filesize_exit
  887.  
  888.             xor     ax,ax                   ;Zero offset.
  889.             xor     dx,dx
  890.             mov     cl,2                    ;Move pointer from end.
  891.             call    move_fileptr            ;Move file pointer
  892.             jc      filesize_exit
  893.  
  894.             call    hex2asc                 ;Convert size to ASCII
  895. filesize_exit:
  896.             ret
  897. filesize_file   endp
  898.  
  899. ;-----------------------------------------------------------------------------
  900. ; TRUENAME FILE  returns the fully qualified name of a file.
  901. ;-----------------------------------------------------------------------------
  902. truename_file   proc    near
  903.             assume  cs:code,ds:code,es:code
  904.             mov     si,var1_value           ;Fully qualify filename
  905.             mov     di,dest_var_val         ;Use dest buff as temp buff
  906.             call    parse_filename
  907.         jnc    truename_1
  908.         mov    si,offset errmsg6    ;Illegal filename msg
  909. truename_1:
  910.             ret
  911. truename_file   endp
  912.  
  913. ;=============================================================================
  914. ; System Functions
  915. ;=============================================================================
  916. ;-----------------------------------------------------------------------------
  917. ; VER SYS returns the DOS version number
  918. ;-----------------------------------------------------------------------------
  919. ver_sys         proc    near
  920.             mov     ax,dos_version
  921.             push    ax
  922.             mov     al,100
  923.             xchg    al,ah                   ;Copy major ver number
  924.             mul     ah
  925.             pop     bx
  926.             xor     bh,bh
  927.             add     ax,bx
  928.             xor     dx,dx
  929.             mov     di,dest_var_val
  930.             call    hex2asc
  931.             clc
  932.             ret
  933. ver_sys         endp
  934.  
  935. ;-----------------------------------------------------------------------------
  936. ; ASK SYS prints a string then returns the user response.
  937. ;-----------------------------------------------------------------------------
  938. ask_sys         proc    near
  939.  
  940.             mov     si,var1_value
  941.             cmp     byte ptr [si],0
  942.             je      ask_1
  943.             call    print_strcr             ;Print result string
  944. ask_1:
  945.             mov     bx,80h
  946.             mov     byte ptr [bx],127
  947.             mov     dx,bx
  948.             mov     ah,0ah
  949.             int     21h
  950.  
  951.             mov     si,offset endmsg
  952.             call    print_str               ;Insert a CR-LF
  953.  
  954.             xor     cx,cx                   ;Append zero to string.
  955.             inc     bx
  956.             mov     cl,[bx]
  957.             inc     bx
  958.             mov     si,bx
  959.             add     bx,cx
  960.             mov     byte ptr [bx],0
  961.             inc     cx
  962.             mov     di,dest_var_val         ;Move string to result buff
  963.             rep     movsb
  964.  
  965.             clc
  966.             ret
  967. ask_sys         endp
  968.  
  969. ;-----------------------------------------------------------------------------
  970. ; RC SYS returns the return code from the prev process
  971. ;-----------------------------------------------------------------------------
  972. rc_sys          proc    near
  973.             mov     ah,4dh                  ;Get return code
  974.             int     21h
  975.             xor     ah,ah
  976.             xor     dx,dx
  977.             mov     di,dest_var_val
  978.             call    hex2asc
  979.             clc
  980.             ret
  981. rc_sys          endp
  982.  
  983. ;-----------------------------------------------------------------------------
  984. ; ENVFREE SYS returns the number of bytes free in the environment.
  985. ;-----------------------------------------------------------------------------
  986. envfree_sys     proc    near
  987.             push    es
  988.  
  989.             cmp     use_mastenv,0        ;Find environment block
  990.             jne     envfree_0
  991.             call    findenv                 ;Use parent's env by default.
  992.             jnc     envfree_01
  993. envfree_0:
  994.             call    findmaster              ;Find master env
  995.             jc      envfree_exit
  996. envfree_01:
  997.             push    ax
  998.             dec     ax
  999.             mov     es,ax
  1000.             mov     dx,es:[3]               ;Get size of env segment
  1001.             mov     cl,4                    ;Convert paragraphs to bytes
  1002.             shl     dx,cl
  1003.             pop     es
  1004.  
  1005.             mov     cx,dx
  1006.             xor     ax,ax
  1007.             xor     di,di
  1008. envfree_1:
  1009.             repne   scasb                   ;Loop through the environment
  1010.             cmp     byte ptr es:[di],al     ;  until the end of the
  1011.             loopne  envfree_1               ;  env strings is found.
  1012.             jcxz    envfree_2
  1013.             mov     ax,dx
  1014.             sub     ax,di
  1015.         dec    ax            ;Sub byte for extra zero
  1016. envfree_2:
  1017.             xor     dx,dx
  1018.             pop     es
  1019.             mov     di,dest_var_val
  1020.             call    hex2asc
  1021.         clc
  1022. envfree_exit:
  1023.             ret
  1024. envfree_sys     endp
  1025.  
  1026. ;-----------------------------------------------------------------------------
  1027. ; ENVSIZE SYS returns the size of the environment.
  1028. ;-----------------------------------------------------------------------------
  1029. envsize_sys     proc    near
  1030.             push    es
  1031.  
  1032.             cmp     use_mastenv,0        ;Find environment block
  1033.             jne     envsize_1
  1034.             call    findenv                 ;Use parent's env by default.
  1035.             jnc     envsize_2
  1036. envsize_1:
  1037.             call    findmaster              ;Find master env
  1038.             jc      envfree_exit
  1039. envsize_2:
  1040.             push    ax
  1041.             dec     ax
  1042.             mov     es,ax
  1043.             mov     ax,es:[3]               ;Get size of env segment
  1044.             mov     cl,4                    ;Convert paragraphs to bytes
  1045.             shl     ax,cl
  1046.             pop     es
  1047.  
  1048.             xor     dx,dx
  1049.             pop     es
  1050.             mov     di,dest_var_val
  1051.             call    hex2asc
  1052.             clc
  1053.             ret
  1054. envsize_sys     endp
  1055.  
  1056. ;-----------------------------------------------------------------------------
  1057. ; MASTERVAR SYS returns the value from a variable in the master environment.
  1058. ;-----------------------------------------------------------------------------
  1059. mastervar_sys   proc    near
  1060.             push    ds
  1061.             push    es
  1062.  
  1063.             mov     di,var1_value
  1064.             push    di
  1065.             call    find_end
  1066.             mov     word ptr es:[di-1],003dh ;Append = sign
  1067.             pop     si
  1068.  
  1069.             call    caps_string
  1070.  
  1071.         push    cx            ;Save length of var name
  1072.             call    findmaster
  1073.         pop    cx
  1074.             jc      mastervar_exit
  1075.             mov     es,ax
  1076.             xor     di,di                   ;Use find string routine to
  1077.             call    findstr                 ;  find the variable name.
  1078.             jnc     mastervar_1
  1079.             mov     si,offset errmsg17
  1080.             stc
  1081.             jmp     short mastervar_exit
  1082. mastervar_1:
  1083.             mov     si,dest_var_val
  1084.             push    es
  1085.             push    ds                      ;Exchange DS:SI and ES:DI
  1086.             pop     es                      ;  pointers.
  1087.             pop     ds
  1088.             xchg    si,di
  1089. mastervar_2:
  1090.             lodsb                           ;Find end of var name.
  1091.             cmp     al,'='
  1092.             jne     mastervar_2
  1093.  
  1094.             call    copy_string
  1095.             clc
  1096. mastervar_exit:
  1097.             pop     ds
  1098.             pop     es
  1099.             ret
  1100. mastervar_sys   endp
  1101.  
  1102. ;=============================================================================
  1103. ; Number Functions
  1104. ;=============================================================================
  1105. ;-----------------------------------------------------------------------------
  1106. ; ADD NUM returns the sum of two numbers
  1107. ;-----------------------------------------------------------------------------
  1108. add_num         proc    near
  1109.             assume  cs:code,ds:code,es:code
  1110.             call    conv2num                ;Convert first two parms to
  1111.             jc      add_num_exit            ;  32 bit numbers.  Carry
  1112.             add     ax,bx                   ;  set, overflow.
  1113.             adc     dx,cx
  1114.             mov     si,offset errmsg12      ;Add overflow
  1115.             jc      add_num_exit            ;If overflow, error
  1116.  
  1117.             mov     di,dest_var_val
  1118.             call    hex2asc                 ;Convert result to ASCII
  1119. add_num_exit:
  1120.             ret
  1121. add_num         endp
  1122.  
  1123. ;-----------------------------------------------------------------------------
  1124. ; SUB NUM returns the difference of two numbers
  1125. ;-----------------------------------------------------------------------------
  1126. sub_num         proc    near
  1127.             assume  cs:code,ds:code,es:code
  1128.             call    conv2num                ;Convert first two parms to
  1129.             jc      sub_num_exit            ;  32 bit numbers.  Carry
  1130.             sub     ax,bx                   ;  set, overflow.
  1131.             sbb     dx,cx
  1132.             mov     si,offset errmsg13      ;Sub underflow
  1133.             jc      sub_num_exit
  1134.  
  1135.             mov     di,dest_var_val
  1136.             call    hex2asc                 ;Convert result to ASCII
  1137. sub_num_exit:
  1138.             ret
  1139. sub_num         endp
  1140.  
  1141. ;-----------------------------------------------------------------------------
  1142. ; MUL NUM returns the product of two numbers
  1143. ;-----------------------------------------------------------------------------
  1144. mul_num         proc    near
  1145.             assume  cs:code,ds:code,es:code
  1146.             push    bp
  1147.             call    conv2num                ;Convert first two parms to
  1148.             jc      mul_num_exit            ;  32 bit numbers.  Carry
  1149.             mov     di,dx                   ;  set, overflow.
  1150.             mov     si,ax
  1151.             mul     cx                      ;32 bit multiply.
  1152.             jc      mul_num_error           ;Param 1 in DI,SI
  1153.             mov     bp,ax                   ;Param 2 in CX,BX
  1154.             mov     ax,di
  1155.             mul     cx                      ;              DI   SI
  1156.             or      ax,dx                   ;              CX   BX
  1157.             jnz     mul_num_error           ; ---------------------
  1158.             mov     ax,di                   ;             (BX * SI)
  1159.             mul     bx                      ;        (BX * DI)
  1160.             jc      mul_num_error           ;        (CX * SI)
  1161.             add     bp,ax                   ; + (CX * DI)
  1162.             mov     ax,si                   ; ---------------------
  1163.             mul     bx                      ;              DX   AX
  1164.             add     dx,bp
  1165.             jc      mul_num_error
  1166.  
  1167.             mov     di,dest_var_val
  1168.             call    hex2asc                 ;Convert result to ASCII
  1169. mul_num_exit:
  1170.             pop     bp
  1171.             ret
  1172. mul_num_error:
  1173.             stc
  1174.             mov     si,offset errmsg10      ;Multiply overflow
  1175.             stc
  1176.             jmp     short mul_num_exit
  1177. mul_num         endp
  1178.  
  1179. ;-----------------------------------------------------------------------------
  1180. ; DIV NUM returns the quotient of two numbers
  1181. ;-----------------------------------------------------------------------------
  1182. div_num         proc    near
  1183.             assume  cs:code,ds:code,es:code
  1184.             call    conv2num                ;Convert first two parms to
  1185.             jc      div_num_exit            ;  32 bit numbers.
  1186.             push    cx
  1187.             or      cx,bx                   ;Prevent divide by zero
  1188.             pop     cx
  1189.             jz      div_num_error
  1190. div_num_1:
  1191.             or      cx,cx                   ;Divide both numbers by 2
  1192.             je      div_num_2               ;  until high word of
  1193.             shr     dx,1                    ;  divisor (CX) is zero.
  1194.             rcr     ax,1
  1195.  
  1196.             shr     cx,1
  1197.             rcr     bx,1
  1198.             jmp     short div_num_1
  1199. div_num_2:
  1200.             push    ax                      ;Save low word
  1201.             mov     ax,dx
  1202.             xor     dx,dx
  1203.             div     bx                      ;Divide high word
  1204.             mov     cx,ax                   ;Save high quotent
  1205.             pop     ax
  1206.             div     bx                      ;Divide low word
  1207.             mov     dx,cx
  1208.  
  1209.             mov     di,dest_var_val
  1210.             call    hex2asc                 ;Convert result to ASCII
  1211. div_num_exit:
  1212.             ret
  1213. div_num_error:
  1214.             mov     si,offset errmsg11
  1215.             stc
  1216.             jmp     short div_num_exit
  1217. div_num         endp
  1218.  
  1219. ;=============================================================================
  1220. ; Support Procedures
  1221. ;=============================================================================
  1222. ;-----------------------------------------------------------------------------
  1223. ; CONV2NUM  converts the first two parameters to hex numbers.
  1224. ; Exit:      DX AX - Number from 1st parameter
  1225. ;            CX BX - Number from 1st parameter
  1226. ;            CF    - Set if either number too large
  1227. ;            SI    - Set to error message if CF set
  1228. ;-----------------------------------------------------------------------------
  1229. conv2num        proc    near
  1230.             mov     si,var2_value           ;Convert 2nd parameter to hex
  1231.             call    asc2hex
  1232.             jc      conv2num_error
  1233.             mov     bx,ax                   ;Copy second parameter
  1234.             mov     cx,dx
  1235.  
  1236.             mov     si,var1_value           ;Convert 1st parameter to hex
  1237.             call    asc2hex
  1238.             jc      conv2num_error
  1239. conv2num_exit:
  1240.             ret
  1241. conv2num_error:
  1242.             mov     si,offset errmsg14      ;Number too large
  1243.             jmp     short conv2num_exit
  1244. conv2num        endp
  1245.  
  1246. ;-----------------------------------------------------------------------------
  1247. ; PARSE CMDLINE  Parse the command line into seperate buffers for each word.
  1248. ; Entry:  SI - Pointer to string to parse.
  1249. ; Exit:   CF - Set if error.
  1250. ;         SI - Points to error message if CF set.
  1251. ;-----------------------------------------------------------------------------
  1252. parse_cmdline   proc    near
  1253.             mov     si,offset command_tail
  1254.             cmp     byte ptr [si],0         ;See if cmdline = 0
  1255.             jne     parse_cmdline_1         ;If zero, report error
  1256. parse_error:
  1257.             mov     si,offset errmsg1       ;Syntax error message
  1258.             stc
  1259.             jmp     parse_cmdline_exit1
  1260. parse_cmdline_1:
  1261.             inc     si
  1262.             xor     cx,cx
  1263.             xor     bx,bx
  1264.             call    scan4char               ;Find 1st char
  1265.             jc      parse_error
  1266.     
  1267.             cmp     al,'/'                  ;See if cmdline switch
  1268.             jne     parse_cmdline_2
  1269.             inc     si                      ;Skip past '/'.
  1270.             lodsb                           ;Get cmdline switch
  1271.         cmp    al,'?'
  1272.         je     parse_cmdline13
  1273.             or      al,20h
  1274.             cmp     al,'m'
  1275.             jne     parse_cmdline_11
  1276.             mov     use_mastenv,1           ;Set use master env flag
  1277.             jmp     short parse_cmdline_1
  1278. parse_cmdline_11:
  1279.             cmp     al,'p'
  1280.             jne     parse_cmdline_12
  1281.             lodsb
  1282.             mov     parse_char,al           ;Set new parse character
  1283.             jmp     short parse_cmdline_1
  1284. parse_cmdline_12:
  1285.             cmp     al,'h'
  1286.             jne     parse_error
  1287. parse_cmdline13:
  1288.         mov    si,offset hlpmsg
  1289.         stc
  1290.         jmp    short parse_cmdline_exit1
  1291. parse_cmdline_2:
  1292.             mov     di,cmd_value
  1293.             mov     bx,203dh                ;copy until = or space
  1294.             call    copy_till
  1295.             jc      parse_cmdline_exit
  1296.             cmp     al,'='
  1297.             je      parse_cmdline_4
  1298. parse_cmdline_3:
  1299.             xor     bl,bl
  1300.             call    scan4char               ;Find next char
  1301.             jc      parse_cmdline_exit
  1302.             cmp     byte ptr [si],'='
  1303.             jne     parse_cmdline_5
  1304.             inc     si                      ;Move src ptr past =
  1305. parse_cmdline_4:
  1306.             mov     console_out,0           ;Clear console out flag
  1307.             xor     bl,bl                   ;Find next char
  1308.             call    scan4char
  1309.             jc      parse_error
  1310.  
  1311.             push    si                      ;If = found, 1st parameter
  1312.             mov     si,cmd_value            ;  was dest var name.  Copy
  1313.             mov     di,dest_var_name        ;  name, then get new cmd
  1314.             call    copy_string             ;  string.
  1315.             pop     si
  1316.  
  1317.             mov     bx,2020h                ;Copy until next space
  1318.             mov     di,cmd_value
  1319.             call    copy_till
  1320.             mov     al,0                    ;Terminate new cmd with 0
  1321.             stosb
  1322.             jc      parse_cmdline_exit
  1323. parse_cmdline_5:
  1324.             mov     bp,offset var1_value
  1325.             mov     cx,3                    ;Max 3 parameters
  1326. parse_cmdline_6:
  1327.             xor     bl,bl                   ;Find start of parameter
  1328.             call    scan4char
  1329.             jc      parse_cmdline_exit
  1330.  
  1331.         mov    bl,parse_char        ;If consecutive parse chars
  1332.         mov    bh,bl            ;  lead a parameter, skip the
  1333.         cmp    [si],bx            ;  characters.  This is used
  1334.         jne    parse_cmdline_7        ;  to allow leading spaces in
  1335.         inc    si            ;  parameters.
  1336.         inc    si
  1337. parse_cmdline_7:
  1338.             mov     di,[bp]                 ;Get ptr to buffer
  1339.             xor     bh,bh
  1340.             call    copy_till        ;Copy until parse char
  1341.             jc      parse_cmdline_exit
  1342.             add     bp,2
  1343.             loop    parse_cmdline_6
  1344. parse_cmdline_exit:
  1345.             clc
  1346. parse_cmdline_exit1:
  1347.             ret
  1348. parse_cmdline   endp
  1349.  
  1350. ;-----------------------------------------------------------------------------
  1351. ; COPY TILL  Copys a string until a specified character is found
  1352. ;   Entry:  SI - Pointer to source string
  1353. ;           DI - Pointer to destination buffer
  1354. ;           BL - 1st end character
  1355. ;           BH - 2nd end character
  1356. ;-----------------------------------------------------------------------------
  1357. copy_till       proc    near
  1358. copytill_1:
  1359.             lodsb
  1360.             cmp     al,13                   ;Check for carriage return.
  1361.             je      copytill_eol
  1362. copytill_2:
  1363.             cmp     al,equalsub_char        ;See if = sub char
  1364.             jne     copytill_3
  1365.             mov     al,'='
  1366. copytill_3:
  1367.             cmp     al,bl                   ;See if end character found
  1368.             je      copytill_exit
  1369.             cmp     al,bh                   ;See if any char at or below
  1370.             jbe     copytill_exit           ;  2nd end character.
  1371.             stosb
  1372.             jmp     short copytill_1
  1373. copytill_exit:
  1374.             clc
  1375. copytill_exit1:
  1376.             ret
  1377. copytill_eol:
  1378.             stc
  1379.             jmp     short copytill_exit1
  1380. copy_till       endp
  1381.  
  1382. ;-----------------------------------------------------------------------------
  1383. ; PARSE FILENAME  creates a proper pathname for a filename
  1384. ;   Entry:  SI - Pointer to ASCIIZ filename
  1385. ;           DI - Pointer to buffer to hold resulting pathname
  1386. ;-----------------------------------------------------------------------------
  1387. parse_filename  proc    near
  1388.             assume  cs:code,ds:code,es:code
  1389.             push    di
  1390.             push    si
  1391.             cmp     dos_version,300h        ;See if DOS 3.x or greater.
  1392.             jb      parse_fname_0           ;If not, parse the old way.
  1393.             mov     ah,60h                  ;DOS Resolve Path
  1394.             int     21h
  1395.             jmp     short parse_fname_7
  1396. parse_fname_0:
  1397.             cmp     byte ptr [SI+1],":"     ;See if disk specified
  1398.             je      parse_fname_1           ;Yes, skip disk assignment
  1399.  
  1400.             mov     ah,19h                  ;Get default disk
  1401.             int     21h
  1402.             inc     al
  1403.  
  1404.             mov     dl,al                   ;Save default disk number
  1405.             add     al,40h                  ;Make ASCII
  1406.             mov     ah,":"
  1407.             jmp     short parse_fname_2
  1408. parse_fname_1:
  1409.             lodsw                           ;Get disk specified
  1410.             and     al,0DFh                 ;Convert to caps
  1411.             mov     dl,al
  1412.             sub     dl,40h                  ;Convert to hex
  1413. parse_fname_2:
  1414.             stosw                           ;Load disk specification
  1415. ;Look for directory specification.
  1416.             mov     bx,di                   ;save start of path
  1417.             mov     al,"\"
  1418.             cmp     byte ptr [si],al        ;See if starting from root
  1419.             je      parse_fname_3            ;Yes, skip append of path
  1420.  
  1421.             stosb                           ;Start at root
  1422.             push    si                      ;Save current pointer
  1423.             mov     si,di                   ;Point to dest buffer
  1424.             mov     ah,47h                  ;Get default path
  1425.             int     21h
  1426.             pop     si
  1427.  
  1428.             cmp     byte ptr [di],0         ;See if NULL path
  1429.             je      parse_fname_3
  1430.  
  1431.             call    find_end                ;Scan to end of path string
  1432.             dec     di                      ;move back before zero
  1433.             mov     al,"\"                  ;Append path string with
  1434.             stosb                           ;  a \.  CX = length of path
  1435. parse_fname_3:
  1436.             add     cx,2                    ;Append filename to path.
  1437.             mov     ax,VAR_SIZE             ;Compute space remaining in
  1438.             sub     ax,cx                   ;  the destination buffer.
  1439.             xchg    cx,ax
  1440.             xor     ah,ah                   ;Clear last char holder
  1441. parse_fname_4:
  1442.             lodsb                           ;Get filename character.  If
  1443.             or      al,al                   ;  end of string, exit.
  1444.             jz      parse_fname_6           ;Else, write char.
  1445.             stosb
  1446.             cmp     ax,".."                 ;If last two chars are ..,
  1447.             jne     parse_fname_5           ;  scan backwards to delete
  1448.             std                             ;  last directory.
  1449.             sub     di,4                    ;First, backup past '\..'
  1450.             mov     al,"\"                  ;Look for directory sep
  1451.             push    cx
  1452.             mov     cx,di                   ;Compute length of path
  1453.             sub     cx,bx
  1454.             repne   scasb                   ;Now, past last directory
  1455.             pop     cx
  1456.             cld                             ;Scan forwards again
  1457.             inc     di                      ;Move back past \
  1458. parse_fname_5:
  1459.             mov     ah,al                   ;Save last character read.
  1460.             loop    parse_fname_4
  1461. parse_fname_6:
  1462.             xor     al,al                   ;Terminate string with 0
  1463.             stosb
  1464. parse_fname_7:
  1465.             pop     si
  1466.             pop     di
  1467.             ret
  1468. parse_filename  endp
  1469.  
  1470. ;-----------------------------------------------------------------------------
  1471. ; CREATE FILE Creates a new file.
  1472. ; Entry:  DX - Pointer to ASCIIZ filename.
  1473. ; Exit:   BX - File handle
  1474. ;         CF - Set if error
  1475. ;-----------------------------------------------------------------------------
  1476. create_file     proc    near
  1477.             push    cx
  1478.             mov     ah,3ch                  ;Create file
  1479.             xor     cx,cx                   ;Normal attributes
  1480.             int     21h
  1481.             mov     bx,ax                   ;Copy file handle
  1482.             pop     cx
  1483.             ret
  1484. create_file     endp
  1485.  
  1486. ;-----------------------------------------------------------------------------
  1487. ; OPEN FILE Opens a file.
  1488. ; Entry:  DX - Pointer to ASCIIZ filename.
  1489. ; Exit:   BX - File handle
  1490. ;         CF - Set if error
  1491. ;-----------------------------------------------------------------------------
  1492. open_file       proc    near
  1493.             mov     ax,3d02h                ;Open file, read/write
  1494.             int     21h
  1495.             mov     bx,ax                   ;Copy file handle
  1496.             ret
  1497. open_file       endp
  1498.  
  1499. ;-----------------------------------------------------------------------------
  1500. ; CLOSE FILE Closes a file.
  1501. ; Entry:  BX - File handle
  1502. ; Exit:   CF - Set if error
  1503. ;-----------------------------------------------------------------------------
  1504. close_file      proc    near
  1505.             mov     ah,3eh                  ;Close file
  1506.             int     21h
  1507.             ret
  1508. close_file      endp
  1509.  
  1510. ;-----------------------------------------------------------------------------
  1511. ; READ FILE Reads data from a file
  1512. ; Entry:  BX - File handle
  1513. ;         CX - Number of bytes to read
  1514. ;         DX - Pointer to data buffer
  1515. ; Exit:   CF - Set if error
  1516. ;         AX - bytes read.
  1517. ;-----------------------------------------------------------------------------
  1518. read_file       proc    near
  1519.             mov     ah,3fh                  ;Read file data
  1520.             int     21h
  1521.             ret
  1522. read_file       endp
  1523.  
  1524. ;-----------------------------------------------------------------------------
  1525. ; WRITE FILE Writes data to a file
  1526. ; Entry:  BX - File handle
  1527. ;         CX - Number of bytes to write
  1528. ;         DX - Pointer to data buffer
  1529. ; Exit:   CF - Set if error
  1530. ;-----------------------------------------------------------------------------
  1531. write_file      proc    near
  1532.             mov     ah,40h                  ;Write file data
  1533.             int     21h
  1534.             ret
  1535. write_file      endp
  1536.  
  1537. ;-----------------------------------------------------------------------------
  1538. ; MOVE FILEPTR Moves the file read pointer of a file.
  1539. ; Entry:  AX,DX - Offset of file pointer
  1540. ;            BX - File handle
  1541. ;            CL - Move type, 0 = from start, 2 = from end.
  1542. ; Exit:      CF - Set if error
  1543. ;-----------------------------------------------------------------------------
  1544. move_fileptr    proc    near
  1545.             xchg    cx,dx                   ;Copy most sig word
  1546.             xchg    dx,ax                   ;Copy least sig word
  1547.             mov     ah,42h                  ;Move file pointer
  1548.             int     21h
  1549.             ret
  1550. move_fileptr    endp
  1551.  
  1552. ;-----------------------------------------------------------------------------
  1553. ; TRUNCNUM truncates a number to the max length of a string
  1554. ; Entry:  AX - Number to truncate
  1555. ; Exit:   AX - Truncated number
  1556. ;-----------------------------------------------------------------------------
  1557. truncnum        proc    near
  1558.             cmp     ax,VAR_SIZE             ;VAR_SIZE = max string length
  1559.             jb      trunc_1
  1560.             mov     ax,VAR_SIZE
  1561. trunc_1:
  1562.             ret
  1563. truncnum        endp
  1564.  
  1565. ;-----------------------------------------------------------------------------
  1566. ; FINDSTR  determines if a string is in a list.
  1567. ; Entry:  DS:SI - Pointer to ASCII string to find.
  1568. ;         ES:DI - Pointer to list of ASCIIZ strings.
  1569. ;            CX - Size of string
  1570. ; Exit:      DI - Pointer to entry in list
  1571. ;            CF - Clear if string found
  1572. ;            BX - If CF clear, index into list
  1573. ;-----------------------------------------------------------------------------
  1574. findstr         proc    near
  1575.             push    cx
  1576.             push    dx
  1577.             xor     dx,dx
  1578.             or      dx,cx                   ;Save length of string
  1579.             je      finds_3
  1580.             xor     bx,bx                   ;Zero index counter
  1581. finds_1:
  1582.             push    di
  1583.             push    si
  1584.             push    cx
  1585.             repe    cmpsb                   ;Compare command
  1586.             pop     cx
  1587.             pop     si
  1588.             pop     di
  1589.             clc
  1590.             je      findstr_exit
  1591.             inc     bx                      ;Inc string count
  1592.  
  1593.             push    cx
  1594.             call    find_endl               ;Find end of string.
  1595.             pop     cx
  1596.             jne     finds_3
  1597.             cmp     byte ptr es:[di],0      ;See if second zero. If so
  1598.             jne     finds_1                 ;  end of list.
  1599. finds_3:
  1600.             stc                             ;Indicate string not found
  1601. findstr_exit:
  1602.             pop     dx
  1603.             pop     cx
  1604.             ret
  1605. findstr         endp
  1606.  
  1607. ;-----------------------------------------------------------------------------
  1608. ; FIND END scans to the end of an ASCIIZ string.
  1609. ; Entry:  ES:DI - Pointer to ASCII string
  1610. ; Exit:   ES:DI - Pointers to character after string.
  1611. ;            CX - Length of string
  1612. ;            ZF - Clear if end not found in MAX length of characters
  1613. ;-----------------------------------------------------------------------------
  1614. find_end        proc    near
  1615.             push    ax
  1616.             mov     cx,VAR_SIZE
  1617.             xor     al,al
  1618.             repne   scasb
  1619.             pushf
  1620.             mov     ax,VAR_SIZE
  1621.             sub     ax,cx
  1622.             xchg    ax,cx
  1623.             dec     cx
  1624.             popf
  1625.             pop     ax
  1626.             ret
  1627. find_end        endp
  1628.  
  1629. ;-----------------------------------------------------------------------------
  1630. ; FIND ENDL scans to the end of an ASCIIZ string. String can be up to 32K
  1631. ; Entry:  ES:DI - Pointer to ASCII string
  1632. ; Exit:   ES:DI - Pointers to character after string.
  1633. ;            CX - Length of string
  1634. ;            ZF - Clear if end not found in MAX length of characters
  1635. ;-----------------------------------------------------------------------------
  1636. find_endl       proc    near
  1637.             push    ax
  1638.             mov     cx,8000h
  1639.             xor     al,al
  1640.             repne   scasb
  1641.             pushf
  1642.             mov     ax,8000h
  1643.             sub     ax,cx
  1644.             xchg    ax,cx
  1645.             dec     cx
  1646.             popf
  1647.             pop     ax
  1648.             ret
  1649. find_endl       endp
  1650.  
  1651. ;-----------------------------------------------------------------------------
  1652. ; CAPS STRING capitalizes ASCIIZ string
  1653. ; Entry:  SI - Pointer to ASCII string to capitalize
  1654. ; Exit:   CX - Length of string
  1655. ;-----------------------------------------------------------------------------
  1656. caps_string     proc near
  1657.             assume  ds:code,es:code
  1658.             push    bx
  1659.             push    dx
  1660.             mov     bx,"za"                 ;Set filter limits
  1661.             mov     dx,0df00h               ;Set character filter
  1662.             call    filter_string
  1663.             pop     dx
  1664.             pop     bx
  1665.             ret
  1666. caps_string     endp
  1667.  
  1668. ;-----------------------------------------------------------------------------
  1669. ; LC STRING makes an ASCIIZ string lower case
  1670. ; Entry:  SI - Pointer to ASCII
  1671. ; Exit:   CX - Length of string
  1672. ;-----------------------------------------------------------------------------
  1673. lc_string       proc near
  1674.             assume  ds:code,es:code
  1675.             push    bx
  1676.             push    dx
  1677.             mov     bx,"ZA"                 ;Set filter limits
  1678.             mov     dx,0ff20h               ;Set character filter
  1679.             call    filter_string
  1680.             pop     dx
  1681.             pop     bx
  1682.             ret
  1683. lc_string       endp
  1684.  
  1685. ;-----------------------------------------------------------------------------
  1686. ; FILTER STRING filters an ASCIIZ string
  1687. ; Entry: DS:SI - Pointer to ASCII string
  1688. ;           BL - Lower limit of char range
  1689. ;           BH - Upper limit of char range
  1690. ;           DL - OR  filter
  1691. ;           DH - AND filter
  1692. ; Exit:     CX - Length of string
  1693. ;-----------------------------------------------------------------------------
  1694. filter_string   proc near
  1695.             assume  ds:code,es:code
  1696.             push    si
  1697.             push    di
  1698.             push    es
  1699.  
  1700.             mov     di,si
  1701.             push    ds
  1702.             pop     es
  1703.             xor     cx,cx                   ;Clear byte counter.
  1704. filter_1:
  1705.             lodsb                           ;Get character
  1706.             or      al,al                   ;Allow any non-space character
  1707.             je      filter_exit
  1708.             cmp     al,bl                   ;If between lower and upper
  1709.             jb      filter_2                ;  char limit it.
  1710.             cmp     al,bh
  1711.             ja      filter_2
  1712.             or      al,dl                   ;Apply OR filter
  1713.             and     al,dh                   ;Apply AND filter
  1714. filter_2:
  1715.             stosb                           ;Save character
  1716.             inc     cx                      ;Inc byte counter
  1717.             jmp     short filter_1
  1718. filter_exit:
  1719.             pop     es
  1720.             pop     di
  1721.             pop     si
  1722.             ret
  1723. filter_string   endp
  1724.  
  1725. ;-----------------------------------------------------------------------------
  1726. ; COPY STRING copies an ASCIIZ string
  1727. ; Entry:  DS:SI - Pointer to source ASCIIZ string
  1728. ;         ES:DI - Pointer to destination buffer
  1729. ; Exit:   CX - Length of string
  1730. ;-----------------------------------------------------------------------------
  1731. copy_string     proc near
  1732.             assume  ds:code,es:code
  1733.             xor     cx,cx
  1734. copy_string_1:
  1735.             lodsb                           ;Move character
  1736.             stosb
  1737.             or      al,al                   ;See if end of string
  1738.             je      copy_string_exit        ;If so, exit
  1739.             inc     cx                      ;Inc count
  1740.             jmp     short copy_string_1
  1741. copy_string_exit:
  1742.             ret
  1743. copy_string     endp
  1744.  
  1745. ;-----------------------------------------------------------------------------
  1746. ; PRINT STRCR prints an ASCIIZ string then appends a CR LF to the end
  1747. ; Entry:  SI - pointer to ASCIIZ string.
  1748. ;-----------------------------------------------------------------------------
  1749. print_strcr     proc    near
  1750.             assume  ds:nothing,es:nothing
  1751.             call    print_str
  1752.             mov     si,offset endmsg
  1753.             call    print_str
  1754.             ret
  1755. print_strcr     endp
  1756.  
  1757. ;-----------------------------------------------------------------------------
  1758. ; PRINT STR  prints an ASCIIZ string to the std output device
  1759. ; Entry:  SI - Pointer to ASCIIZ string.
  1760. ;-----------------------------------------------------------------------------
  1761. print_str       proc    near
  1762.             lodsb                           ;Get character
  1763.             or      al,al                   ;See if end of string
  1764.             je      print_str_exit
  1765.             mov     ah,2                    ;DOS print character
  1766.             mov     dl,al
  1767.             int     21h                     ;Call DOS
  1768.             jmp     short print_str
  1769. print_str_exit:
  1770.             ret
  1771. print_str       endp
  1772.  
  1773. ;-----------------------------------------------------------------------------
  1774. ; HEX2ASC converts number in DX AX to ASCII
  1775. ; Entry:  DX AX - Number
  1776. ;         DI - Destination buffer
  1777. ;         CF - Clear
  1778. ;-----------------------------------------------------------------------------
  1779. hex2asc         proc near
  1780.             assume  ds:nothing,es:nothing
  1781.             push    ax
  1782.             push    bx
  1783.             push    cx
  1784.             push    dx
  1785.             push    si
  1786.  
  1787.             mov     si,10                   ;Load number base
  1788.             mov     bx,ax
  1789.             mov     cx,dx
  1790.             mov     dx,-1                   ;Load end of number flag
  1791.             push    dx
  1792. hex_loop1:
  1793.             xchg    ax,cx                   ;Get high word in AX
  1794.             xor     dx,dx                   ;Clear high word
  1795.             div     si                      ;Divide by base (10)
  1796.             xchg    cx,ax                   ;Save result of high divide
  1797.             xchg    ax,bx                   ;Get low word, leave remainder
  1798.             div     si                      ;  in DX.
  1799.             xchg    bx,ax                   ;Save result of low divide
  1800.  
  1801.             add     dl,30h                  ;Convert to ascii
  1802.             push    dx                      ;Save digit on stack
  1803.             or      bx,bx
  1804.             jne     hex_loop1               ;See if number = 0.  If not,
  1805.             or      cx,cx                   ;  continue divide loop.
  1806.             jne     hex_loop1
  1807.  
  1808.             mov     bl,"0"                  ;Set leading zero flag
  1809. hex_loop2:
  1810.             pop     dx                      ;Get digit off stack
  1811.             cmp     dx,-1                   ;See if end flag
  1812.             je      hex_2
  1813.             or      bl,dl                   ;Don't print leading zeros.
  1814.             cmp     bl,"0"                  ;The first non zero will
  1815.             je      hex_1                   ;  change bl to non-zero.
  1816.             mov     al,dl                   ;Write to buffer
  1817.             stosb
  1818. hex_1:
  1819.             jmp     short hex_loop2
  1820. hex_2:
  1821.             cmp     bl,"0"                  ;If number zero, write last
  1822.             jne     hex_exit                ;  zero.
  1823.             mov     al,bl
  1824.             stosb
  1825. hex_exit:
  1826.             xor     al,al                   ;Termainate with zero
  1827.             stosb
  1828.             pop     si
  1829.             pop     dx
  1830.             pop     cx
  1831.             pop     bx
  1832.             pop     ax
  1833.             ret
  1834. hex2asc         endp
  1835.  
  1836. ;-----------------------------------------------------------------------------
  1837. ; ASC2HEX converts an ASCII number to hex
  1838. ; Entry:     SI - Pointer to ASCIIZ string, max 5 digits.
  1839. ; Exit:   DX,AX - Number
  1840. ;            CF - Set if overflow
  1841. ;-----------------------------------------------------------------------------
  1842. asc2hex         proc    near
  1843.             assume  ds:nothing,es:nothing
  1844.             push    bx
  1845.             push    cx
  1846.             push    bp
  1847.             xor     cx,cx                   ;Zero result
  1848.             xor     di,di
  1849.             xor     bx,bx
  1850.             mov     bp,10                   ;Load number base
  1851. asc_loop1:
  1852.             mov     bl,[si]                 ;Get next digit
  1853.             inc     si
  1854.             sub     bl,"0"                  ;Convert digit from ASCII to
  1855.             jb      asc_exit                ;  hex.  If digit illegal
  1856.             cmp     bl,9                    ;  character, exit.
  1857.             ja      asc_exit
  1858.  
  1859.             xchg    ax,di                   ;Shift result in DI CX by
  1860.             mul     bp                      ;  the base.
  1861.             jc      asc_exit1
  1862.             xchg    di,ax
  1863.             xchg    ax,cx
  1864.             mul     bp
  1865.             xchg    cx,ax
  1866.         add    di,dx
  1867.         jc    asc_exit1
  1868.  
  1869.             add     cx,bx                   ;Add new number to result.
  1870.             adc     di,0
  1871.             jnc     short asc_loop1
  1872. asc_exit1:
  1873.             mov     ax,cx                   ;Copy result
  1874.             mov     dx,di
  1875.             pop     bp
  1876.             pop     cx
  1877.             pop     bx
  1878.             ret
  1879. asc_exit:
  1880.             clc
  1881.             jmp     short asc_exit1
  1882. asc2hex         endp
  1883.  
  1884. ;-----------------------------------------------------------------------------
  1885. ; SCAN4CHAR scans a string to find the first character.
  1886. ; Entry:  SI - pointer to ASCII string
  1887. ;         BL - 0 = find next char,
  1888. ;              1 = find next space,
  1889. ;              2 = find end of line,
  1890. ;              3 = find next space or =.
  1891. ;              4 = find character in DL.
  1892. ; Exit:   AL - matching character
  1893. ;         SI - pointer to matching character
  1894. ;         CF - set if carriage return or EOF found
  1895. ;-----------------------------------------------------------------------------
  1896. scan4char       proc near
  1897.             assume  ds:nothing,es:nothing
  1898. scan4loop:
  1899.             lodsb
  1900.             cmp     al,13                   ;Check for carriage return.
  1901.             jne     scan4_1
  1902. scan4_eol:
  1903.             stc
  1904.             jmp     short scan4_exit1
  1905. scan4_1:
  1906.             cmp     bl,4
  1907.             je      scan4_dl
  1908.             cmp     bl,3
  1909.             je      scan4_equal
  1910.             cmp     bl,1                    ;Check if searching for space,
  1911.             je      scan4_space             ;  character, or end of line.
  1912.             ja      scan4loop
  1913.             cmp     al," "                  ;Check for space or other
  1914.             jbe     scan4loop               ;  'white' characters.
  1915.             jmp     short scan4_exit
  1916. scan4_dl:
  1917.             cmp     al,dl                   ;Check for parse character
  1918.             je      scan4_exit
  1919.             jmp     short scan4loop
  1920. scan4_equal:
  1921.             cmp     al,"="                  ;Check for exit
  1922.             je      scan4_exit
  1923. scan4_space:
  1924.             cmp     al," "                  ;Check for characters.
  1925.             ja      scan4loop
  1926. scan4_exit:
  1927.             dec     si                      ;Back up before character
  1928.             clc
  1929. scan4_exit1:
  1930.             ret
  1931. scan4char       endp
  1932.  
  1933. ;-----------------------------------------------------------------------------
  1934. ; PAUSE SCR Prints a 'press key' message then waits for one.
  1935. ;-----------------------------------------------------------------------------
  1936. pause_scr    proc    near
  1937.         mov    si,offset pausemsg
  1938.         call    print_strcr
  1939. pause_1:
  1940.         int    28h            ;Call Idle interrupt
  1941.         cld
  1942.         mov    ah,01            ;Check for key press
  1943.         int    16h
  1944.         jz    pause_1
  1945.         xor    ax,ax            ;Get key from buffer
  1946.         int    16h
  1947.         ret
  1948. pause_scr    endp
  1949.  
  1950. ;-----------------------------------------------------------------------------
  1951. ; FINDENV  Finds the parent's environment block.
  1952. ; Exit:    AX - Segment of local command processor environment.
  1953. ;-----------------------------------------------------------------------------
  1954. findenv         proc    near
  1955.             assume  cs:code,ds:code,es:code,ss:code
  1956.         push    di
  1957.         push    si
  1958.             push    es
  1959. findenv_1:
  1960.             mov     ax,es:[16h]             ;Get parent's PSP
  1961.         mov    dx,ax            ;Save PSP segment
  1962.         push    ax
  1963.         dec    ax            ;Point to mcb
  1964.         mov    es,ax
  1965.             cmp     byte ptr es:[0],"M"     ;check for mcb signature
  1966.         pop    es
  1967.             jne     findenv_error
  1968.         
  1969.         cmp    dx,es:[16h]        ;See if PSP is own parent
  1970.         jne    findenv_1        ;No, keep looking
  1971.  
  1972.         mov    cx,30        
  1973.         mov    es,ax
  1974. findenv_2:        
  1975.             add     ax,es:[3]               ;Add size of memory block
  1976.         inc    ax
  1977.             mov     es,ax
  1978.  
  1979.             cmp     byte ptr es:[0],"M"     ;check for mcb signature
  1980.             jne     findenv_error
  1981.             cmp     dx,es:[1]               ;See if this owned by cmd proc
  1982.             je      findenv_3
  1983.             loop    findenv_2
  1984.             jmp     short findenv_error
  1985. findenv_3:
  1986.         inc    ax
  1987.             clc
  1988. findenv_exit:
  1989.             pop     es
  1990.         pop    si
  1991.         pop    di
  1992.             ret
  1993. findenv_error:
  1994.         mov    si,offset errmsg16    ;Environment not found
  1995.         stc
  1996.         jmp    short findenv_exit
  1997. findenv         endp
  1998.  
  1999. ;-----------------------------------------------------------------------------
  2000. ; FINDMASTER  Finds the master environment block.
  2001. ; Exit:  AX - Segment of Master environment block
  2002. ;-----------------------------------------------------------------------------
  2003. findmaster      proc    near
  2004.             assume  cs:code,ds:code,es:code,ss:code
  2005.             push    di
  2006.             push    si
  2007.             push    es
  2008.  
  2009.             mov     ah,52h                  ;Get address of first MCB
  2010.             int     21h
  2011.             mov     ax,es:[bx-2]            ;point ES to MCB
  2012.             mov     cx,30                   ;Allow only 30 loops.
  2013. findmaster_1:
  2014.             mov     es,ax
  2015.             cmp     byte ptr es:[0],"M"     ;check for mcb signature
  2016.             jne     findmaster_exit
  2017.             inc     ax                      ;point AX to memory block
  2018.             cmp     ax,es:[1]               ;See if this is a PSP block
  2019.             je      findmaster_4
  2020. findmaster_2:
  2021.             add     ax,es:[3]               ;Get size of memory block
  2022.             loop    findmaster_1
  2023.             jmp     short findmaster_error
  2024.  
  2025. findmaster_4:
  2026.             cmp     dos_version,0a00h       ;If OS/2, use DOS 3.3 method.
  2027.             jae     findmaster_5
  2028.             cmp     dos_version,0400h       ;If DOS 4.00 or greater,
  2029.             jb      findmaster_5            ;  COMMAND.COM may not be the
  2030.             push    ds                      ;  first program loaded.  Look
  2031.             mov     si,offset shell_name    ;  at the name of the program
  2032.             mov     di,8                    ;  stored in the last 8 bytes
  2033.             mov     cx,7                    ;  of the memory control
  2034.             repe    cmpsb                   ;  block.  If the string
  2035.             pop     ds                      ;  "COMMAND" isn't found, keep
  2036.             jne     findmaster_1            ;  looking.
  2037. findmaster_5:
  2038.             mov     dx,ax                   ;Save PSP seg
  2039.             mov     es,ax
  2040.             mov     bx,es:[2ch]             ;Get seg of prog environment
  2041.             mov     ax,bx
  2042.             dec     bx
  2043.             mov     es,bx
  2044.             cmp     byte ptr es:[0],"M"     ;See if valid memory block
  2045.             je      findmaster_found
  2046.             mov     ax,dx                   ;Get back cmd.com segment
  2047.             dec     ax                      ;Point back to mcb
  2048.             mov     es,ax
  2049. findmaster_6:
  2050.             add     ax,es:[3]               ;If master env segment not
  2051.             inc     ax                      ;  saved at 2Ch of the PSP,
  2052.             mov     es,ax                   ;  scan the memory blocks
  2053.             cmp     es:[1],dx               ;  for first segment owned
  2054.             je      findmaster_7            ;  above the PSP.
  2055.             loop    findmaster_6
  2056. findmaster_error:
  2057.             mov     si,offset errmsg16      ;Master env not found msg
  2058.             stc
  2059.             jmp     short findmaster_exit   ;Master env not found.
  2060. findmaster_7:
  2061.             inc     ax                      ;Point AX to env segment
  2062. findmaster_found:
  2063.             clc
  2064. findmaster_exit:
  2065.             pop     es
  2066.             pop     si
  2067.             pop     di
  2068.             ret
  2069. findmaster      endp
  2070.  
  2071. ;-----------------------------------------------------------------------------
  2072. ; SETENV  Sets environment variables.
  2073. ;
  2074. ; Entry:  DS:SI - pointer to env var name
  2075. ;         ES:DI - pointer to env var value
  2076. ;-----------------------------------------------------------------------------
  2077. setenv          proc    near
  2078.             push    bp
  2079.             push    ds
  2080.             push    es
  2081.  
  2082.             push    di            ;Save ptr to var value
  2083.             push    es
  2084.  
  2085.             call    find_end                ;Get length of var value
  2086.             mov     dx,cx                   ;Copy length
  2087.             mov     di,si
  2088.             push    ds                      ;Add length of var name plus
  2089.             pop     es                      ;  room for the equals sign.
  2090.             call    find_end
  2091.             mov     word ptr es:[di-1],003dh ;Append = sign
  2092.             inc     cx                       ;Add byte for =
  2093.             add     dx,cx
  2094.             inc     dx                      ;Add byte for terminating 0
  2095.  
  2096.             mov     ax,environment_seg
  2097.             push    ax
  2098.             dec     ax
  2099.             mov     es,ax
  2100.             mov     bp,es:[3]               ;Get size of env segment
  2101.             push    cx
  2102.             mov     cl,4                    ;Convert paragraphs to bytes
  2103.             shl     bp,cl
  2104.             pop     cx
  2105.             pop     es
  2106.  
  2107.             xor     di,di                   ;Use find string routine to
  2108.             call    findstr                 ;  find the variable name.
  2109.  
  2110.             push    si
  2111.             push    ds
  2112.             jc      setenv_2                ;Var not found, skip erase
  2113.             push    es
  2114.             pop     ds
  2115.  
  2116.             mov     si,di                   ;Erase current var value by
  2117.             call    find_endl               ;  copying the next env var
  2118.             xchg    si,di                   ;  over the current one.
  2119. setenv_1:
  2120.             cmp     byte ptr [si],0
  2121.             je      setenv_2
  2122. setenv_11:
  2123.             lodsb
  2124.             stosb
  2125.             or      al,al
  2126.             jne     setenv_11
  2127.             jmp     short setenv_1
  2128. setenv_2:
  2129.             pop     ax                      ;Get ptr to var name
  2130.             pop     cx
  2131.  
  2132.             pop     ds                      ;Get ptr to var value
  2133.             pop     si
  2134.  
  2135.         cmp    byte ptr ds:[si],0    ;See if NULL variable, If so,
  2136.         je    setenv_31        ;  don't add to env block
  2137.  
  2138.             mov     bx,di                   ;Get offset of end of env
  2139.             add     bx,dx                   ;Add length of value
  2140.             inc     bx                      ;Add length of terminating byte
  2141.             cmp     bp,bx
  2142.             ja      setenv_3
  2143.  
  2144.             push    ax            ;Save ptr to var name
  2145.         push    cx
  2146.         mov    dx,es
  2147.         dec    dx
  2148.         mov    es,dx        
  2149.         push    es:[1]            ;Save current owner segment
  2150.         inc    dx
  2151.         mov    es,dx
  2152.             add     bx,15                   ;If no room in environemnt,
  2153.             mov     cl,4                    ;  see if env segment can be
  2154.             shr     bx,cl                   ;  resized to make room for
  2155.             mov     ah,4ah                  ;  new variable.
  2156.             int     21h                     ;Reallocate memory
  2157.         pop    bx            ;Get old owner
  2158.         pop    cx
  2159.             pop     ax
  2160.             jc      setenv_5
  2161.         push    es
  2162.         dec    dx
  2163.         mov    es,dx
  2164.         mov    es:[1],bx        ;Restore old owner 
  2165.         pop    es
  2166. setenv_3:
  2167.             push    si
  2168.             push    ds
  2169.  
  2170.             mov     si,cx
  2171.             mov     ds,ax
  2172.             call    copy_string             ;Copy var name to env
  2173.             dec     di                      ;Back up over last zero
  2174.             pop     ds
  2175.             pop     si
  2176.  
  2177.             mov     bl,"="                  ;Since env vars can't have
  2178.             mov     bh,bl                   ;  the char '=', filter
  2179.             mov     dl,-1                   ;  string to change = to
  2180.             mov     dh,equalsub_char        ;  graphic char that looks
  2181.             call    filter_string           ;  similar.
  2182.  
  2183.             call    copy_string             ;Copy var value to env
  2184. setenv_31:
  2185.             xor     al,al
  2186.             stosb                           ;Add 2 zeros to end env.
  2187. setenv_4:
  2188.             clc                             ;Set pass flag
  2189. setenv_5:
  2190.             pop     es
  2191.             pop     ds
  2192.             pop     bp
  2193.             ret
  2194. setenv          endp
  2195.  
  2196. initialize      endp
  2197.             even                            ;Set stack on word boundry
  2198. end_of_code     =       $
  2199. code            ends
  2200.  
  2201. end             main
  2202.